package com.qf.smsplatform.interfaces.service.impl;

import com.qf.smsplatform.common.constants.CacheConstants;
import com.qf.smsplatform.common.constants.RabbitMQConstants;
import com.qf.smsplatform.common.constants.ReportStateConstants;
import com.qf.smsplatform.common.constants.SourceType;
import com.qf.smsplatform.common.enums.SmsPlatformEnums;
import com.qf.smsplatform.common.exception.SmsPlatfromEx;
import com.qf.smsplatform.common.model.StandardSubmit;
import com.qf.smsplatform.interfaces.form.SmsInterfaceForm;
import com.qf.smsplatform.interfaces.service.InterfaceService;
import com.qf.smsplatform.interfaces.service.api.CacheService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @Author: LeeRui
 * 2021/1/26 下午 8:32
 **/
@Service
@Slf4j
public class InterfaceServiceImpl implements InterfaceService {

    //通过Spring工厂注入CacheService交互Redis
    @Autowired
    private CacheService cacheService;

    //通过spring工厂注入RabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //校验用户请求参数
    @Override
    public void checkParamters(SmsInterfaceForm smsInterfaceForm) {
        //======================校验clientID=============================
        //==============101	认证错误 ientId错误==========================
        //获取用户传入的form对象中的clientID
        String clientID = smsInterfaceForm.getClientID();
        //Redis缓存中查询校验clientID
        Map map = cacheService.hMGet(CacheConstants.CACHE_PREFIX_CLIENT + clientID);
        //若map为空，则校验clientID失败
        if (map == null || map.size() == 0) {
            log.info("【校验clientID】 认证错误：clientId错误  clientID={}", clientID);
            throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_CLIENT_ID_ERROR);
        }

        //======================校验pwd===================================
        //=================102	密码错误==================================
        //获取用户传入的form对象中的pwd
        String pwd = smsInterfaceForm.getPwd();
        //从校验clientID通过之后获取的map中校验pwd(Redis中pwd为大写)
        //需要使用apache的common项目中的codec的依赖给用户传入的密码加密并转为大写再进行校验比对
        if (StringUtils.isEmpty(pwd) || !DigestUtils.md5Hex(pwd).toUpperCase().equals(map.get("pwd"))) {
            log.info("【校验pwd】 密码错误  pwd={}", pwd);
            throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_PWD_ERROR);
        }

        //======================校验ip====================================
        //=================103	IP校验错误=================================
        //获取用户传入的form对象中的ip
        String ip = smsInterfaceForm.getIp();
        //从校验clientID通过之后获取的map中获取ipaddress并转为String类型
        String ipAddress = (String) map.get("ipaddress");
        //声明一个flag
        Boolean flag = false;
        //将ipaddress通过逗号拆分并进行遍历，再进行校验
        String[] ipaddr = ipAddress.split(",");
        for (String str : ipaddr) {
            if (!StringUtils.isEmpty(ip) && ip.equals(str)) {
                //校验通过
                flag = true;
                break;
            }
        }
        //判断flag
        if (!flag) {
            log.info("【校验ip】 IP校验错误  ip={}", ip);
            throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_IP_ERROR);
        }

        //======================校验content===============================
        //=================104	消息长度错，为空或超长（目前定为500个字）====
        //获取用户传入的form对象中的content
        String content = smsInterfaceForm.getContent();
        //校验content
        if (StringUtils.isEmpty(content) || clientID.length() > 500) {
            log.info("【校验content】 消息长度错，为空或超长（目前定为500个字）  content={}", content);
            throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_CONTENT_ERROR);
        }

        //======================校验mobile================================
        //=================105	手机号码错误=================================
        //获取用户传入的form对象中的手机号码
        String mobiles = smsInterfaceForm.getMobile();
        //校验手机号码是否为空
        if (StringUtils.isEmpty(mobiles)) {
            log.info("【校验mobile】 手机号码错误  mobiles={}", mobiles);
            throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_MOBILE_ERROR);
        }
        //校验手机号码个数是否超过100个
        //通过逗号拆分手机号码为数组
        String[] mobileArr = mobiles.split(",");
        //校验手机号码个数
        if (mobileArr.length > 100) {
            log.info("【校验mobile】 手机号码错误  mobileArr={}", Arrays.toString(mobileArr));
            throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_MOBILE_ERROR);
        }
        //正则表达式校验手机号码格式,只要有错误格式的手机号码就判定失败
        String regex = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$";
        //创建Set集合存入错误的手机号码
        Set<String> errorMobile = new HashSet<>();
        //遍历手机号码拆分后的数组进行格式校验
        for (String mobile : mobileArr) {
            if (!mobile.matches(regex)) {
                errorMobile.add(mobile);
            }
        }
        //将错误的手机号码存入一个集合返回给用户
        if (errorMobile.size() > 0) {
            log.info("【校验mobile】 手机号码错误  mobileArr={}", Arrays.toString(mobileArr));
            throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_MOBILE_ERROR, errorMobile);
        }

        //======================校验srcID=================================
        //=================106	下行编号（srcID）错误======================
        //获取用户传入的form对象中的srcID
        String srcIDStr = smsInterfaceForm.getSrcID();
        Long srcID = null;
        //校验，若srcID不为空则转为Long类型
        if (!StringUtils.isEmpty(srcIDStr)) {
            try {   //若转换异常则说明传入的srcID格式不正确
                srcID = Long.parseLong(srcIDStr);
            } catch (NumberFormatException e) {
                log.info("【校验srcID】 下行编号（srcID）错误  srcID={}", srcID);
                throw new SmsPlatfromEx(SmsPlatformEnums.INTERFACE_SRCID_ERROR);
            }
        }


        //=====================若用户参数校验通过，则发送消息到MQ===========================
        for (String mobile : mobileArr) {
            //TODO submit的唯一标识sequenceId,需要在这里封装,但是暂时先不封装
            //TODO 目前已在gateway模块在mq监听中利用工具类指定了sequenceId

            StandardSubmit standardSubmit = new StandardSubmit();
            standardSubmit.setClientID(Integer.parseInt(clientID));
            standardSubmit.setSendTime(new Date());
            standardSubmit.setDestMobile(mobile);
            standardSubmit.setMessageContent(content);
            standardSubmit.setMessagePriority(Short.parseShort((String) map.get("priority")));
            standardSubmit.setSource(SourceType.HTTP);
            standardSubmit.setSrcSequenceId(srcID);
            standardSubmit.setReportState(ReportStateConstants.WAIT);
            rabbitTemplate.convertAndSend(RabbitMQConstants.TOPIC_PRE_SEND + "_exchange","suibianxie",standardSubmit);
        }
    }
}
